package gl.java.network.transport.kcp.umsp;

import gl.java.network.transport.kcp.core.ChannelOptionHelper;
import gl.java.network.transport.kcp.core.UkcpChannel;
import gl.java.network.transport.kcp.core.UkcpChannelOption;
import gl.java.network.transport.kcp.core.UkcpServerChannel;
import gl.java.umsp.*;
import gl.java.umsp.gateway.GateWayMessageDispatcher;
import gl.java.umsp.room.RoomConnectionHandler;
import gl.java.umsp.room.RoomMessageDispatcher;
import io.netty.bootstrap.UkcpServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class UmspKcpServer {


    static Logger log = LoggerFactory.getLogger(UmspKcpServer.class);

    public static void main(String[] args) throws Exception {
        int PORT = Integer.parseInt(System.getProperty("port", "8897"));
        if (args!=null&&args.length>0){
            PORT = Integer.parseInt(args[0]);
        }
        start(PORT);
    }

    public static void start(final int port) throws InterruptedException {
        // Configure the server.
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            UkcpServerBootstrap b = new UkcpServerBootstrap();
            b.group(group)
                    .channel(UkcpServerChannel.class)
                    .childHandler(new ChannelInitializer<UkcpChannel>() {
                        @Override
                        public void initChannel(UkcpChannel ch) throws Exception {
                            ChannelPipeline p = ch.pipeline();
                            p.addLast(
                                    UmspAutoHeartBeatHandler.newTimeOutCloseHandler(ch.pipeline()),
                                    new UmspKcpConnectionHandler(),
                                    new UmspMessageUnpacker(),
                                    new UmspMessagePacker(),
                                    new UmspMessageDecoder(),
                                    new RoomConnectionHandler(),
                                    new RoomMessageDispatcher());
                        }
                    });
            ChannelOptionHelper.nodelay(b, true, 20, 2, true)
                    .childOption(UkcpChannelOption.UKCP_MTU, 512);

            // Start the server.
            ChannelFuture f = b.bind(port).sync();
            f.addListener(new GenericFutureListener<Future<? super Void>>() {
                @Override
                public void operationComplete(Future<? super Void> future) throws Exception {
                    log.info("===============================================");
                    log.info("===    KcpServer is running at port" + port+"    ===");
                    log.info("===============================================");
                }
            });
            // Wait until the server socket is closed.
            f.channel().closeFuture().sync();
        } finally {
            // Shut down all event loops to terminate all threads.
            group.shutdownGracefully();
        }
    }
}
